/*

  The contents of this file are subject to the Mozilla Public License Version
  1.1 (the "License"); you may not use this file except in compliance with
  the License. You may obtain a copy of the License at 
  
           http://www.mozilla.org/MPL/ 
  
  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  for the specific language governing rights and limitations under the License. 
  
  The Original Code is Indigo framework applicatif.
  
  The Initial Developer of the Original Code is
  Olivier Bugalotto (aka Iteratif) <olivier.bugalotto@iteratif.net>.
  Portions created by the Initial Developer are Copyright (C) 2004-2008
  the Initial Developer. All Rights Reserved.
  
  Contributor(s) :
  
*/
package indigo.air.updaters
{
	import flash.desktop.NativeApplication;
	import flash.desktop.Updater;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;
	
	import indigo.air.errors.CheckError;
	
	/**
	 * La classe <code>UpdateHelper</code> s'occupe pour vous de l'existance d'une mise a jour
	 * de l'application AIR, la nouvelle version est telechargee et installee.
	 * @author iteratif
	 * 
	 */
	public class UpdaterHelper extends EventDispatcher
	{
		public static const UPDATE_NAME:String = "update.air";
		public static const DIRECTORY:String = "updates";
		
		private static var air_ns:Namespace = new Namespace("http://ns.adobe.com/air/application/1.0");
		
		private var _ctrlPoint:String;
		private var _process:Function;
		private var _info:UpdateInfo;
		
		/**
		 * Obtenir le chemin du point de contrôle
		 * @return 
		 * 
		 */
		public function get ctrlPoint():String {
			return _ctrlPoint;
		}
		
		/**
		 * Definit le point de controle distant de la mise a jour
		 * @param value ressource locale ou distante
		 * 
		 */
		public function set ctrlPoint(value:String):void {
			_ctrlPoint = value;
		}
		
		/**
		 * 
		 * @param ctrlPoint
		 * 
		 */
		public function UpdaterHelper(ctrlPoint:String = null)
		{
			super();
			_ctrlPoint = ctrlPoint;
		}
		
		/**
		 * Appel d'une ressource locale ou distante pour verifier s'il existe une mise a jour de l'application
		 * @param process reference d'une methode de traitement des donnees chargees
		 * <p>
		 * La signature de cette methode est de type:
		 * <code>function processMethod(data:Object):UpdateInfo;</code>
		 * </p>
		 * 
		 * @see UpdateInfo
		 */
		public function check(process:Function):void {
			if(process == null) throw new CheckError();
			
			_process = process;
			
			var loader:URLLoader = new URLLoader();
			// TODO: gèrer la non disponibilité du fichier de version
			loader.addEventListener(Event.COMPLETE,onLoadTicket);
			loader.load(new URLRequest(ctrlPoint));
		}
		
		private function onLoadTicket(e:Event):void {
			var loader:URLLoader = e.target as URLLoader;
			_info = _process(loader.data);
			
			var currentVersion:String = NativeApplication.nativeApplication.applicationDescriptor.air_ns::version.toString();
			
			if(currentVersion != _info.version && _info.airFile.length > 0) {
				var stream:URLStream = new URLStream();
				// TODO: gèrer la non disponibilité du fichier de mise a jour
				stream.addEventListener(Event.COMPLETE,onUploadedApplication);
				stream.load(new URLRequest(_info.airFile));
			}
		}
		
		private function onUploadedApplication(e:Event):void {
			var stream:URLStream = e.target as URLStream;
			stream.removeEventListener(Event.COMPLETE,onUploadedApplication);
			var buffer:ByteArray = new ByteArray();
			stream.readBytes(buffer,0,stream.bytesAvailable);
			stream.close();
			
			var storage:File = File.applicationStorageDirectory;
			var storageUpdate:File = storage.resolvePath(DIRECTORY+"/"+UPDATE_NAME);
			var fStream:FileStream = new FileStream();
			fStream.open(storageUpdate,FileMode.WRITE);
			fStream.writeBytes(buffer);
			fStream.close();
			
			var updater:Updater = new Updater();
			updater.update(storageUpdate,_info.version);
		}
	}
}